package com.alibaba.citrus.cr.price.ability.functions.entity.activity;

import com.alibaba.citrus.cr.common.annotation.FunctionInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.util.SpringContextUtil;
import com.alibaba.citrus.cr.price.repository.ActivityWriteRepository;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.epoch.app.crpricecenter.sdo.ActivityTitleExtSDO;
import com.epoch.app.crpricecenter.sdo.ActivityUseRecordRelationSDO;
import lombok.Data;

import java.util.Objects;

/**
 * @author: qiaojiange
 * @create: 2021/10/17
 * @Description 活动抬头扩展表
 */
@Data
public class ActivityTitleExtEntity {

    private static Log log = Log.getLogger(ActivityTitleExtEntity.class);

    /**
     * 写入资源库
     */
    private static ActivityWriteRepository writeRepository = SpringContextUtil.getBean(ActivityWriteRepository.class);

    private ActivityTitleExtSDO sdo;

    /**
     * 需要保存的标
     */
    private Boolean needSaveFlag = false;

    public static ActivityTitleExtEntity of(ActivityTitleExtSDO sdo) {
        ActivityTitleExtEntity titleExtEntity = new ActivityTitleExtEntity();
        titleExtEntity.setSdo(sdo);
        return titleExtEntity;
    }

    /**
     * 保存方法
     */
    public void save() {
        //不需要保存，直接返回
        if (!needSaveFlag) {
            return;
        }
        //保存的逻辑当前测试无法覆盖，故当前不做开发
    }

    /**
     * 活动申请费用
     * @return
     */
    public Long obtainApplyFee() {
        return this.sdo == null ? null : this.sdo.getApplyFee();
    }

    public void setVersion(Integer version) {
        this.sdo.setVersion(version);
    }


    /**
     * 更新活动数量和金额_活动回补, 注意该方法只是内存修改，没有保存到数据库的逻辑
     *
     * @param activityEntity
     * @return
     */
    public Boolean updateOccupyQuantityAndFeeForCover(ActivityEntity activityEntity) {
        /**
         * 更新占用活动数量
         */
        Boolean occupyQuantityFlag = this.updateOccupyQuantityForCover(activityEntity);
        /**
         * 更新占用活动金额
         */
        Boolean occupyFeeFlag = this.updateOccupyFeeForCover(activityEntity);

        return occupyQuantityFlag && occupyFeeFlag;
    }


    @FunctionInvoker
    private Boolean updateOccupyQuantityForCover(ActivityEntity activityEntity) {
        //    这个地方要进行判断
        ActivityUseRecordRelationSDO useSDO = activityEntity.getUseEntity().getActivityUseRecordRelationSDO();
        if (Objects.isNull(useSDO)) {
            log.error("活动回补失败,该订单没有活动使用记录");
            throw new FacadeException("OTS-08-002-01-16-007");
        }

        Long itemQuantity = this.obtainActivityOccupyQuantity() - useSDO.getItemQuantity();
        //活动回补时，进行活动占补量的判断
        if (itemQuantity < 0) {
            log.error("活动占用量不够回补，该货品回补活动失败！活动回补活动量:{}, 已经占用的活动量:{},本次要占用的活动量:{}",
                    this.sdo.getApplyItemQuantity(), this.obtainActivityOccupyQuantity(), itemQuantity);
            return false;
        }
        log.info(activityEntity.getTitleEntity().obtainActivityId()+"ActivityTitleExtEntity.updateOccupyQuantityForCover.obtainActivityOccupyQuantity"+obtainActivityOccupyQuantity()
                +"useSDO.getItemQuantity()"+useSDO.getItemQuantity()+"itemQuantity"+itemQuantity+"useSDO.id"+ JSON.toJSONString(useSDO));
        this.sdo.setActivityOccupyQuantity(itemQuantity);
//        this.sdo.setVersion(termRequest.getVersion());
        needSaveFlag = true;
        ActivitySaveFlagThreadLocal.set(true);
        log.info("activityId{},needSaveFlag{},ActivitySaveFlagThreadLocal{}",activityEntity.getTitleEntity().obtainActivityId(),needSaveFlag,ActivitySaveFlagThreadLocal.get());
        return true;

    }


    @FunctionInvoker
    private Boolean updateOccupyFeeForCover(ActivityEntity activityEntity) {
        ActivityUseRecordRelationSDO useSDO = activityEntity.getUseEntity().getActivityUseRecordRelationSDO();
        if (Objects.isNull(useSDO)) {
            log.error("活动回补失败,该订单没有活动使用记录");
            throw new FacadeException("OTS-08-002-01-16-007");
        }
        Long thisPreOccupyFee = useSDO.getActivityOccupyFee();
        //本次预占用费用
        //long thisPreOccupyFee = item.getItemPrice() * item.getItemQuantity();
        Long activityOccupyFee = this.obtainActivityOccupyFee() - useSDO.getActivityOccupyFee();
        if (activityOccupyFee < 0) {
            log.error("活动占用回补数量失败！活动申请费用:{},活动已占用费用:{},本次申请费用:{}",
                    this.obtainApplyFee(), this.obtainActivityOccupyFee(), thisPreOccupyFee);
            return false;
        }
        log.info("ActivityTitleExtEntity.updateOccupyFeeForCover.obtainActivityOccupyFee"+obtainActivityOccupyFee()
                +"useSDO.getActivityOccupyFee()"+useSDO.getActivityOccupyFee()+"activityOccupyFee"+activityOccupyFee+"useSDO.id"+useSDO.getId());
        this.sdo.setActivityOccupyFee(activityOccupyFee);
        //this.sdo.setVersion(termRequest.getVersion());
        needSaveFlag = true;
        ActivitySaveFlagThreadLocal.set(true);
        log.info("activityId{},needSaveFlag{},ActivitySaveFlagThreadLocal{}",activityEntity.getTitleEntity().obtainActivityId(),needSaveFlag,ActivitySaveFlagThreadLocal.get());
        return true;
    }

    private Long obtainActivityOccupyFee() {
        return sdo.getActivityOccupyFee();
    }

    private Long obtainActivityOccupyQuantity() {
        return sdo.getActivityOccupyQuantity();
    }

    public Boolean saveNotForVersion() {

        if (!needSaveFlag) {
            return false;
        }
        return writeRepository.updateNotForVersion(this.sdo);
    }

    public Boolean saveForVersion() {
        boolean saveFlag = ActivitySaveFlagThreadLocal.get();
        log.info("Term{},needSaveFlag{},ActivitySaveFlagThreadLocal{}",JSON.toJSONString(this.sdo),needSaveFlag,ActivitySaveFlagThreadLocal.get());
        if (!saveFlag) {
            return false;
        }
        return writeRepository.updateForVersion(this.sdo);
    }

    /**
     * 当前的活动项目申请的总金额和总费用预占的校验
     */
    public Boolean isCanOccupyTerm(Integer quantitySum, Long feeSum) {
        //活动剩余量
        Long remainingQuantity = this.obtainActivityRemainingQuantity();
        //活动剩余量不够
        if (remainingQuantity < quantitySum) {
            log.error("活动占用数量超出申请数量!" +
                    "活动申请量：" + this.obtainApplyItemQuantity() +
                    " 活动已占用量：" + this.obtainActivityOccupyQuantity() +
                    " 活动剩余量：" + remainingQuantity +
                    " 本次活动预占用量：" + quantitySum);
            return false;
        }

        //活动剩余费用
        Long remainingFee = this.obtainActivityRemainingFee();

        //活动剩余量不够
        if (remainingFee < feeSum) {
            log.error("活动占用费用超出申请数量!" +
                    "活动申请费用：" + this.obtainApplyFee() +
                    "活动已占用费用：" + this.obtainActivityOccupyFee() +
                    "活动剩余费用：" + remainingFee +
                    "活动占用费用：" + feeSum);
            return false;
        }
        needSaveFlag = true;
        return true;
    }

    /**
     * 活动剩余费用
     *
     * @return
     */
    private Long obtainActivityRemainingFee() {
        return sdo.getApplyFee() - sdo.getActivityOccupyFee();
    }

    /**
     * 活动申请数量
     *
     * @return
     */
    private Long obtainApplyItemQuantity() {
        return sdo.getApplyItemQuantity();
    }

    /**
     * 活动剩余数量
     *
     * @return
     */
    private Long obtainActivityRemainingQuantity() {
        return sdo.getApplyItemQuantity() - sdo.getActivityOccupyQuantity();
    }

    public void flushOccupyQuantityAndFee(Integer quantitySum, Long feeSum, Integer version) {
        Long activityOccupyQuantity = this.obtainActivityOccupyQuantity();
        this.sdo.setActivityOccupyQuantity(activityOccupyQuantity + quantitySum);
        //乐观锁版本设置为请求体中的版本
        this.setVersion(version);

        //设置新的活动占用费用
        Long activityOccupyFee = this.obtainActivityOccupyFee();
        this.sdo.setActivityOccupyFee(activityOccupyFee + feeSum);
    }

    /**
     * 活动占用
     *
     * @return
     */
    public Boolean updateOccupyQuantityAndFee() {
        if (!needSaveFlag) {
            return false;
        }
        return writeRepository.updateActivityTitleExtOccupyQuantityAndFee(sdo);
    }

    public Integer obtainVersion() {
        return sdo == null ? null : sdo.getVersion();
    }
}
